package com.wuze.cloud.service.impl;

import com.wuze.cloud.adapter.SysFileAdapter;
import com.wuze.cloud.adapter.SysFolderAdapter;
import com.wuze.cloud.context.UserContext;
import com.wuze.cloud.dao.SysFileDao;
import com.wuze.cloud.dao.SysFolderDao;
import com.wuze.cloud.dao.SysFolderRelationDao;
import com.wuze.cloud.enums.SysFileTypeEnum;
import com.wuze.cloud.enums.SysStateEnum;
import com.wuze.cloud.exception.SysGlobalException;
import com.wuze.cloud.pojo.SysFileDO;
import com.wuze.cloud.pojo.SysFolderDO;
import com.wuze.cloud.pojo.SysFolderRelationDO;
import com.wuze.cloud.pojo.SysUserDO;
import com.wuze.cloud.request.SysCreateFolderQuery;
import com.wuze.cloud.request.SysDownloadQuery;
import com.wuze.cloud.request.SysFolderQuery;
import com.wuze.cloud.request.SysUpdateFolderQuery;
import com.wuze.cloud.response.SysFolderListResponse;
import com.wuze.cloud.response.SysFolderResponse;
import com.wuze.cloud.response.SysFolderVO;
import com.wuze.cloud.service.SysFileService;
import com.wuze.cloud.service.SysFolderService;
import org.assertj.core.util.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static com.wuze.cloud.enums.SysGlobalExceptionEnum.*;
import static com.wuze.cloud.enums.SysStateEnum.CREATE;

/**
 * @author: wuze
 * @description:
 * @date: 2023/02/18
 */
@Service
public class SysFolderServiceImpl implements SysFolderService {

    @Autowired
    private SysFolderAdapter folderAdapter;

    @Autowired
    private SysFileAdapter fileAdapter;

    @Autowired
    private SysFolderDao folderDao;

    @Autowired
    private SysFileDao fileDao;

    @Autowired
    private SysFolderRelationDao folderRelationDao;

    @Autowired
    private SysFileService fileService;

    /**
     * 分页查询
     * @param query
     * @return
     */
    @Override
    public SysFolderResponse findByPage(SysFolderQuery query) {
        SysUserDO user = UserContext.getUser();
        if(Objects.isNull(query.getUserId())){
            query.setUserId(user.getId());
        }

        SysFolderResponse response = new SysFolderResponse();
        //查询当前文件夹信息
        SysFolderDO currFolder = folderDao.findOne(query);

        Integer total = folderRelationDao.count(query,SysStateEnum.StateOfCode(query.getState()));
        if (total == 0) {
            response.setFolderVO(folderAdapter.buildSysFolderVO(currFolder));
            response.setTotal(total);
            response.setChildFolders(Lists.newArrayList());
            response.setFiles(Lists.newArrayList());
            return response;
        }

        //查询关联表
        List<SysFolderRelationDO> relationDOS = folderRelationDao.findByPage(query,SysStateEnum.StateOfCode(query.getState()));
        //过滤文件夹id
        Set<Long> folderIds = relationDOS.stream()
                .filter(relationDO -> SysFileTypeEnum.FOLDER_FILE.name().equals(relationDO.getType()))
                .map(SysFolderRelationDO::getChildId)
                .collect(Collectors.toSet());
        //过滤文件id
        Set<Long> fileIds = relationDOS.stream()
                .filter(relationDO -> !SysFileTypeEnum.FOLDER_FILE.name().equals(relationDO.getType()))
                .map(SysFolderRelationDO::getChildId)
                .collect(Collectors.toSet());

        List<SysFolderDO> childList = new ArrayList<>();
        List<SysFileDO> files = new ArrayList<>();
        //查询子文件夹
        if (!CollectionUtils.isEmpty(folderIds)) {
            childList.addAll(folderDao.findByIds(folderIds));
        }
        //查询子文件列表
        if (!CollectionUtils.isEmpty(fileIds)) {
            files.addAll(fileDao.findByIds(fileIds,CREATE.name()));
        }
        //构建当前文件夹vo
        response.setFolderVO(folderAdapter.buildSysFolderVO(currFolder));

        //构建子文件夹list
        response.setChildFolders(folderAdapter.buildSysFolderVOS(childList));
        //构建子文件list
        response.setFiles(fileAdapter.buildSysFileVOS(files));
        response.setTotal(total);
        return response;
    }

    /**
     * 查询文件夹列表
     * @param query
     * @return
     */
    @Override
    public List<SysFolderVO> findList(SysFolderQuery query) {
        SysUserDO user = UserContext.getUser();
        List<SysFolderDO> folders = folderDao.findList(user.getId(), SysStateEnum.StateOfCode(query.getState()));
        return folderAdapter.buildSysFolderVOS(folders);
    }

    /**
     * 查询文件夹列表及其子文件夹
     * @param query
     * @return
     */
    @Override
    public SysFolderListResponse findListv2(SysFolderQuery query) {
        SysUserDO user = UserContext.getUser();
        return folderAdapter.buildSysFolderListResponse(query.getId(),SysStateEnum.StateOfCode(query.getState()));
    }

    /**
     * 创建文件夹
     * @param query 创建文件夹请求实体
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(SysCreateFolderQuery query) {
        SysUserDO user = UserContext.getUser();
        //校验请求
        verifyCreateQuery(query);
        //构建文件夹实体
        SysFolderDO folder = folderAdapter.buildSysFolderDO(query, user);
        //保存文件夹信息
        folderDao.save(folder);
        //保存文件夹关系表
        folderRelationDao.add(folderAdapter.buildRelationDO(user, folder));

    }


    /**
     * 校验创建文件夹请求
     * @param request
     */
    private void verifyCreateQuery(SysCreateFolderQuery request) {
        SysUserDO user = UserContext.getUser();

        SysFolderQuery query = new SysFolderQuery();
        query.setPid(request.getPid());
        query.setUserId(user.getId());
        query.setName(request.getFolderName());
        SysFolderDO folder = folderDao.findByName(query,CREATE.name());
        if (Objects.nonNull(folder)) {
            throw new SysGlobalException(FOLDER_REPEAT.getCode(), FOLDER_REPEAT.getMsg());
        }

    }

    /**
     * 修改文件夹
     * @param query
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(SysUpdateFolderQuery query) {
        //校验修改数据请求
        SysFolderDO folder = verifyUpdateFolderQuery(query);

        //修改文件夹表数据
        folder.setPid(query.getPid());
        folder.setFolderName(query.getFolderName());
        folderDao.update(folder);
        //修改文件夹关系表数据
        folderRelationDao.update(query.getId(), query.getPid(), query.getFolderName());

    }

    /**
     * 校验修改文件夹请求
     * @param query
     * @return
     */
    private SysFolderDO verifyUpdateFolderQuery(SysUpdateFolderQuery query){
        SysUserDO user = UserContext.getUser();
        SysFolderQuery folderQuery = new SysFolderQuery();
        folderQuery.setUserId(user.getId());
        folderQuery.setPid(query.getPid());
        folderQuery.setId(query.getId());
        folderQuery.setName(query.getFolderName());


        if(query.getPid().equals(query.getId())){
            throw new SysGlobalException(PID_ERROR.getCode(), PID_ERROR.getMsg());
        }
        SysFolderDO folder = folderDao.findByName(folderQuery,CREATE.name());
        if (Objects.nonNull(folder)) {
            throw new SysGlobalException(FOLDER_REPEAT.getCode(), FOLDER_REPEAT.getMsg());
        }
        folder = folderDao.findOne(folderQuery);
        if (Objects.isNull(folder)) {
            throw new SysGlobalException(FILE_NOT_FOUND.getCode(), FILE_NOT_FOUND.getMsg());
        }

        return folder;
    }

    /**
     * 批量下载
     * @param query
     * @param response
     */
    @Override
    public void batchDownload(SysDownloadQuery query, HttpServletResponse response) {
        fileService.batchDownload(query,response);
    }
}
